package com.ruubypay.web.core.generator.plugins;

import java.text.SimpleDateFormat;
import java.util.*;
import com.ruubypay.web.core.generator.entity.MethodEntity;
import com.ruubypay.web.core.generator.util.ParameterUtil;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.DefaultJavaFormatter;
import org.mybatis.generator.api.dom.java.*;

public class MybatisServicePlugin extends BizExtendPlugin {

	/**
	 * Describe: 添加引用
	 * Administrator 2017年6月24日
	 */
	@Override
	public void commonImportGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		Set<FullyQualifiedJavaType> importTypeSet= new HashSet<FullyQualifiedJavaType>();
		importTypeSet.add(new FullyQualifiedJavaType("javax.annotation.Resource"));
		topLevelClass.addImportedTypes(importTypeSet);

	}

	/**
	 * Describe: 名字转换
	 * MrShuai 2017年6月24日
	 */
	@Override
	public void commonNameFormatGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

	}

	/**
	 * Describe: 创建Java文件 - 业务接口
	 * MrShuai 2017年6月24日
	 */
	public void createInterfaceGenerated(IntrospectedTable introspectedTable, String domainName, List<GeneratedJavaFile> files) {

	    Interface iFace = new Interface(new FullyQualifiedJavaType("com.ruubypay.biz.mvc."+domainLowerName+".service."+ domainName +"Service"));
        iFace.setVisibility(JavaVisibility.PUBLIC);
        iFace.addJavaDocLine("/**\n * Desc:" + domainName + "控制器\n * @author " + userName + "\n * Date : "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+"\n */");
        
		/**
		 * Desc : SystemUser控制器
		 * @author sucyun
		 * Date : 2018/3/14 下午3:39
		 */

	    Method save = new Method();
		save.addJavaDocLine("/**\n\t * Desc: 保存\n\t * @author "+userName+"\n\t * @param "+domainFirstLowerName+" 保存对象\n\t * @return 返回插入行数\n\t * Date : "+new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())+"\n\t */");
		save.setVisibility(JavaVisibility.PUBLIC);
        save.setName("save"+ domainName);
        save.setReturnType(new FullyQualifiedJavaType("int"));
        save.addParameter(new Parameter(new FullyQualifiedJavaType(domainName),domainFirstLowerName));

        Method remove = new Method();
		remove.addJavaDocLine("/**\n\t * Desc: 删除\n\t * @author "+userName+"\n\t * @param idArray 删除ID数组\n\t * @return 返回删除行数 \n\t * Date : "+new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())+"\n\t */");
        remove.setVisibility(JavaVisibility.PUBLIC);
        remove.setName("remove"+ domainName);
        remove.setReturnType(new FullyQualifiedJavaType("int"));
        remove.addParameter(new Parameter(new FullyQualifiedJavaType("String"),"idArray"));

		Method selectOne = new Method();
		selectOne.addJavaDocLine("/**\n\t * Desc: 根据ID查询\n\t * @author "+userName+"\n\t * @param "+domainFirstLowerName+"Id 查询ID值\n\t * @return 返回ID对应对象\n\t * Date : "+new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())+"\n\t */");
		selectOne.setVisibility(JavaVisibility.PUBLIC);
		selectOne.setName("select"+ domainName +"ById");
		selectOne.setReturnType(new FullyQualifiedJavaType(domainName));
		selectOne.addParameter(new Parameter(new FullyQualifiedJavaType("Integer"),domainFirstLowerName+"Id"));

		Method update = new Method();
		update.addJavaDocLine("/**\n\t * Desc: 修改\n\t * @author "+userName+"\n\t * @param "+ domainFirstLowerName +" 修改对象\n\t * @return 返回修改行数\n\t * Date : "+new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())+"\n\t */");
		update.setVisibility(JavaVisibility.PUBLIC);
		update.setName("update"+ domainName);
		update.setReturnType(new FullyQualifiedJavaType("int"));
		update.addParameter(new Parameter(new FullyQualifiedJavaType(domainName),domainFirstLowerName));

        Method listData = new Method();
		listData.addJavaDocLine("/**\n\t * Desc: 列表页数据查询\n\t * @author "+userName+"\n\t * @param param 查询条件\n\t * @param pageNo 起始页\n\t * @param pageSize 每页大小\n\t * @return 返回列表数据\n\t * Date : "+new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date())+"\n\t */");
        listData.setVisibility(JavaVisibility.PUBLIC);
        listData.setName("listData"+ domainName);
        listData.setReturnType(new FullyQualifiedJavaType("DataGrid"));
		listData.addParameter(new Parameter(new FullyQualifiedJavaType("Map<String,Object>"),"param"));
		listData.addParameter(new Parameter(new FullyQualifiedJavaType("Integer"),"pageNo"));
		listData.addParameter(new Parameter(new FullyQualifiedJavaType("Integer"),"pageSize"));

        iFace.addMethod(save);
        iFace.addMethod(remove);
		iFace.addMethod(selectOne);
		iFace.addMethod(update);
        iFace.addMethod(listData);

        iFace.addImportedType(new FullyQualifiedJavaType("java.util.Map"));
		iFace.addImportedType(new FullyQualifiedJavaType("com.ruubypay.web.common.page.DataGrid"));
        iFace.addImportedType(new FullyQualifiedJavaType("com.ruubypay.biz.mvc."+domainLowerName+".model."+ domainName));

        GeneratedJavaFile file = new GeneratedJavaFile(iFace, workspace +"/src/main/java",new DefaultJavaFormatter());
        files.add(file);

	}

	/**
	 * Describe: 创建Java文件 - 实现类
	 * MrShuai 2017年6月24日
	 */
	@Override
	public void createClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String domainName, List<GeneratedJavaFile> files) {
		//创建接口业务层接口
        createInterfaceGenerated(introspectedTable, domainName, files);

	    //添加类注释
		topLevelClass.setVisibility(JavaVisibility.PUBLIC);
		topLevelClass.addJavaDocLine("/**\n * Desc:" + domainName + " 业务层实现类\n * @author " + userName + "\n * @Date "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+" \n */");
		String tableLowerName = domainName.substring(0, 1).toLowerCase() + domainName.substring(1, domainName.length());
		topLevelClass.addAnnotation("@Service(\""+ tableLowerName + "Service\")");
		topLevelClass.addSuperInterface(new FullyQualifiedJavaType(domainName +"Service"));
		//添加方法
		Field field = new Field();
		// 设置变量名
		field.setName(tableLowerName+"Dao");
		// 类型
		field.setType(new FullyQualifiedJavaType(introspectedTable.getMyBatis3JavaMapperType()));
		field.setVisibility(JavaVisibility.PRIVATE);
		if (enableAnnotation) {
			field.addAnnotation("@Resource");
		}
		topLevelClass.addField(field);
		topLevelClass.addMethod(saveModel(introspectedTable, domainName));
		topLevelClass.addMethod(removeModel(introspectedTable, domainName));
		topLevelClass.addMethod(selectOneModel(introspectedTable, domainName));
		topLevelClass.addMethod(updateMode(introspectedTable, domainName));
		topLevelClass.addMethod(listDataModelByParam(introspectedTable, domainName));
		topLevelClass.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Service"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Resource"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("java.util.Map"));

		topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ruubypay.web.common.page.DataGrid"));
		topLevelClass.addImportedType(new FullyQualifiedJavaType("com.github.pagehelper.PageHelper"));
		topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ruubypay.web.common.page.PageBean"));
		topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ruubypay.web.db.jdbc.DynamicDataSourceHolder"));
		topLevelClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.Logger"));
		topLevelClass.addImportedType(new FullyQualifiedJavaType("org.slf4j.LoggerFactory"));

        topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ruubypay.biz.mvc."+domainLowerName+".service."+ domainName +"Service"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ruubypay.biz.mvc."+domainLowerName+".dao."+ domainName +"Mapper"));
        topLevelClass.addImportedType(new FullyQualifiedJavaType("com.ruubypay.biz.mvc."+domainLowerName+".model."+ domainName));

		GeneratedJavaFile file = new GeneratedJavaFile(topLevelClass, workspace +"/src/main/java",new DefaultJavaFormatter());
		files.add(file);
	}

	/**
	 * Describe: 添加全局对象
	 * MrShuai 2017年6月24日
	 */
	@Override
	public void createFieldGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String tableName) {

	}

	/**
	 * Describe: 创建方法
	 * MrShuai 2017年6月24日
	 */
	@Override
	public void createMethodGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String tableName) {

	}

	/**
	 * Describe: 添加类注释
	 * MrShuai 2017年6月24日
	 */
	@Override
	public void commentjavaFileGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String tableName) {

	}

	/**
	 * Describe: 添加方法注释
	 * MrShuai 2017年6月24日
	 */
	@Override
	public void commentMethodGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

	}

	/**
	 * Describe: 保存对象方法
	 * MrShuai 2017年8月11日
	 */
    private Method saveModel(IntrospectedTable introspectedTable, String domainName) {
        MethodEntity entity = new MethodEntity();
        entity.setJavaDocLine("/**\n\t* Desc: 保存方法\n\t* "+userName+" "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+"\n\t*/");
        entity.setName("save"+domainName);
        entity.setReturnType(new FullyQualifiedJavaType("int"));
        entity.setBodyLine("DynamicDataSourceHolder.setDataSource(\"dataSource_ops\");"+t+"return "+ domainFirstLowerName +"Dao.insert("+domainFirstLowerName+");");
        entity.put(domainFirstLowerName,new FullyQualifiedJavaType(domainName));
		return generatorMethod(entity);
	}

	/**
	 * Describe: 删除对象方法
	 * MrShuai 2017年8月11日
	 */
    private Method removeModel(IntrospectedTable introspectedTable, String domainName) {
        MethodEntity entity = new MethodEntity();
        entity.setJavaDocLine("/**\n\t* Desc: 删除方法\n\t* "+userName+" "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+"\n\t*/");
        entity.setName("remove"+domainName);
        entity.setReturnType(new FullyQualifiedJavaType("int"));
		entity.setBodyLine("DynamicDataSourceHolder.setDataSource(\"dataSource_ops\");"+t+"return "+ domainFirstLowerName +"Dao.deleteByPrimaryKey(idArray);");
        entity.put("idArray",new FullyQualifiedJavaType("String"));
        return generatorMethod(entity);
	}

	/**
	 * Describe: 根据ID查询方法
	 * MrShuai 2017年8月11日
	 */
	private Method selectOneModel(IntrospectedTable introspectedTable, String domainName) {
		MethodEntity entity = new MethodEntity();
		entity.setJavaDocLine("/**\n\t* Desc: 根据ID查询\n\t* "+userName+" "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+"\n\t*/");
		entity.setName("select"+domainName+"ById");
		entity.setReturnType(new FullyQualifiedJavaType(domainName));
		entity.setBodyLine("DynamicDataSourceHolder.setDataSource(\"dataSource_ops\");"+t+"return "+domainFirstLowerName+"Dao.selectByPrimaryKey("+domainFirstLowerName+"Id);");
		entity.put(domainFirstLowerName+"Id",new FullyQualifiedJavaType("Integer"));
		return generatorMethod(entity);
	}

	/**
	 * Describe: 更新修改对象方法
	 * MrShuai 2017年8月11日
	 */
    private Method updateMode(IntrospectedTable introspectedTable, String domainName) {
        MethodEntity entity = new MethodEntity();
        entity.setJavaDocLine("/**\n\t* Desc: 修改方法\n\t* "+userName+" "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+"\n\t*/");
        entity.setName("update"+domainName);
        entity.setReturnType(new FullyQualifiedJavaType("int"));
		entity.setBodyLine("DynamicDataSourceHolder.setDataSource(\"dataSource_ops\");"+t+"return "+ domainFirstLowerName +"Dao.updateByPrimaryKey("+ domainFirstLowerName +");");
        entity.put(domainFirstLowerName,new FullyQualifiedJavaType(domainName));
        return generatorMethod(entity);
	}

	/**
	 * Describe: 根据条件查询对象列表方法
	 * MrShuai 2017年8月11日
	 */
    private Method listDataModelByParam(IntrospectedTable introspectedTable, String domainName) {
		MethodEntity entity = new MethodEntity();
        entity.setJavaDocLine("/**\n\t* Desc: 列表页数据\n\t* "+userName+" "+new SimpleDateFormat("yyyy年MM月dd日").format(new Date())+"\n\t*/");
        entity.setName("listData"+domainName);
        entity.setReturnType(new FullyQualifiedJavaType("DataGrid"));

        StringBuilder sb = new StringBuilder();
        sb.append("DynamicDataSourceHolder.setDataSource(\"dataSource_ops\");");
		sb.append(t+"PageHelper.startPage(pageNo, pageSize);");
		sb.append(t+"List<").append(domainName).append("> ").append(domainFirstLowerName).append("List = ").append(domainFirstLowerName).append("Dao.findAll(param);");
		sb.append(t+"PageBean<").append(domainName).append("> page = new PageBean<>(").append(domainFirstLowerName).append("List);");
		sb.append(t+"return new DataGrid(page.getTotal(), page.getList());");

        entity.setBodyLine(sb.toString());
        entity.put("param",new FullyQualifiedJavaType("Map<String,Object>"));
		entity.put("pageNo",new FullyQualifiedJavaType("Integer"));
		entity.put("pageSize",new FullyQualifiedJavaType("Integer"));
        return generatorMethod(entity);
	}

    /**
     * 创建 method 模版方法
     * @param methodEntity method属性实体类
     * @return method 对象
     */
	private Method generatorMethod(MethodEntity methodEntity){
        Method method = new Method();
        method.addJavaDocLine(methodEntity.getJavaDocLine());
        method.setName(methodEntity.getName());
        method.addAnnotation("@Override");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(methodEntity.getReturnType());
        method.addBodyLine(methodEntity.getBodyLine());
        ParameterUtil.setParameter(method,methodEntity.getParameterMap());
        return method;
    }
}
